Skip to content

167 combinatorial test bed fixes#169

Merged
eviltester merged 6 commits into
masterfrom
167-combinatorial-test-bed-fixes
Jun 9, 2026
Merged

167 combinatorial test bed fixes#169
eviltester merged 6 commits into
masterfrom
167-combinatorial-test-bed-fixes

Conversation

@eviltester

@eviltester eviltester commented Jun 9, 2026

Copy link
Copy Markdown
Owner

closes #167

Summary by CodeRabbit

  • New Features

    • Added live-updating combinatorial estimate output with accessibility status messaging.
    • Added progress indicator with animated visual feedback during execution.
    • Added confirmation dialog for algorithm selection based on estimated row counts.
  • UI/UX

    • Improved layout constraints and sizing for better panel display.
    • Enhanced visual feedback with animated spinner during processing.

Copilot AI review requested due to automatic review settings June 9, 2026 12:28
@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@eviltester, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 59 minutes and 6 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 1d1ab977-5727-490a-a07f-d0f38a3fa94a

📥 Commits

Reviewing files that changed from the base of the PR and between a4bee9c and 019f12e.

📒 Files selected for processing (4)
  • apps/web/combinatorial.html
  • apps/web/src/combinatorial-entry.mjs
  • apps/web/src/tests/jest/combinatorial-entry.test.js
  • apps/web/styles.css
📝 Walkthrough

Walkthrough

This PR refactors the combinatorial page module into a modular factory-based architecture. It adds estimation calculations for cartesian row counts and theoretical minimum coverage rows, displays live estimates in a new UI container, implements an async confirmation flow for cartesian-product generation above a 10,000-row threshold, provides progress indicators with running state animation, and includes comprehensive Jest tests covering estimation logic, confirmation flow, and page initialization.

Changes

Combinatorial Estimation & Progress Workflow

Layer / File(s) Summary
UI Markup, Imports & Display Constants
apps/web/combinatorial.html, apps/web/src/combinatorial-entry.js
New <div id="combinatorial-estimates"> and <p id="combinatorial-progress"> HTML containers with ARIA live regions for estimate output and progress reporting. Module imports add NWiseCoverageModel and confirmation dialog service. New CARTESIAN_CONFIRM_THRESHOLD constant (10,000 rows) and formatNumber helper for rendering finite numbers and infinity bounds.
Estimation & Sort Utilities
apps/web/src/combinatorial-entry.js
Pure functions calculateTheoreticalMinimumRows, calculateRequiredTupleCount, buildEstimateSummary, and sortResultsByRowCount compute cartesian rows, coverage minimums, tuple counts, and sort results by row count then runtime. Also includes async filterAlgorithmsForCartesianConfirmation that removes cartesian-product algorithm when threshold exceeded, plus createIdleStats helper for failed algorithm runs.
Page Factory & DOM Orchestration
apps/web/src/combinatorial-entry.js
createCombinatorialPage factory encapsulates DOM wiring, renders strength/strategy controls, updates estimates on selection changes, validates schema input, runs selected algorithms sequentially with browser yields, captures per-algorithm failures as idle stats, updates progress/status elements during execution, renders sorted summary table and per-run details, and manages generate button state. initCombinatorialPage bootstrapper validates required DOM elements, creates confirmation service, constructs page via factory, and auto-initializes when document is available. Removes legacy top-level render/generate code and updates module exports.
Estimate Display & Progress Animation Styles
apps/web/styles.css
New .combinatorial-estimates grid container with spacing, border, rounded corners, and background tint; nested strong rule for emphasis. .combinatorial-progress base styling with [data-state='running']::before pseudo-element rendering animated spinner dot. Updated .combinatorial-schema-panel/.combinatorial-results with min-width: 0 grid constraint and expanded .combinatorial-schema-editor with max/min-width and box-sizing. New @keyframes combinatorial-spin animation for running-state indicator.
Jest Test Coverage
apps/web/src/tests/jest/combinatorial-entry.test.js
Test setup with createCombinatorialDom() helper constructing JSDOM with all combinatorial UI elements and post-test cleanup. Unit test verifies buildEstimateSummary returns correct cartesian-row counts, theoretical minimums, and tuple totals. Async test confirms filterAlgorithmsForCartesianConfirmation excludes cartesian-product when mocked dialog returns false and validates confirmation payload. Integration test initializes combinatorial page in JSDOM, verifies cartesian unchecked by default, checks estimate text updates with strength changes, and closes window.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant initCombinatorialPage
  participant createCombinatorialPage
  participant DOM
  participant Algorithms
  participant Results
  User->>initCombinatorialPage: DOM ready
  initCombinatorialPage->>DOM: Find elements
  initCombinatorialPage->>createCombinatorialPage: Construct with DOM refs
  createCombinatorialPage->>DOM: Render strength/strategy controls
  createCombinatorialPage->>DOM: Update estimates on strength change
  User->>Results: Click generate
  Results->>createCombinatorialPage: Validate & filter algorithms
  createCombinatorialPage->>Algorithms: Run sequentially with yields
  Algorithms->>DOM: Update progress/status
  Algorithms->>Results: Capture output & failures
  createCombinatorialPage->>Results: Sort by row count & render table
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A rabbit's ode to estimates and progress true,
Where cartesian counts bloom in shades of new.
Spinning animations dance as strategies run,
Sorted results gleam—the estimation is done!
Modular pages now bloom at the root. 🌱✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly references the issue number and describes the main change: fixes for the combinatorial test bed UI and functionality.
Linked Issues check ✅ Passed All four coding objectives from issue #167 are implemented: size estimation with cartesian count display [#167], running indicator and progress updates [#167], cartesian product not selected by default with 10k+ row warning modal [#167], and results table sorted by row count ascending [#167].
Out of Scope Changes check ✅ Passed All changes in the PR directly support the four requirements from issue #167; no unrelated modifications are present in the code or styling updates.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 167-combinatorial-test-bed-fixes

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses issue #167 by improving the Combinatorial Strategies page UX: it adds up-front size/coverage estimates, adds a running/progress indicator while strategies execute, removes cartesian product from default selection, and sorts strategy metrics by smallest row count first.

Changes:

  • Show cartesian size + n-wise lower-bound/tuple estimates and update them when the selected n changes.
  • Add a running/progress indicator and update status as the generator switches strategies.
  • Make results ordering deterministic by sorting strategy metrics (and details) by fewest rows first, and gate large cartesian runs behind a confirmation.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
apps/web/styles.css Adds layout fixes plus new styles for estimates panel and running/progress spinner.
apps/web/combinatorial.html Adds the estimates container and a dedicated progress/status element for live updates.
apps/web/src/combinatorial-entry.js Implements estimates calculation, progress updates, cartesian confirmation filtering, and sorted results rendering.
apps/web/src/tests/jest/combinatorial-entry.test.js Adds Jest coverage for estimates, cartesian confirmation filtering, and default-selection/estimate updates.

Comment thread apps/web/src/combinatorial-entry.js
Comment thread apps/web/src/combinatorial-entry.js
Comment thread apps/web/src/combinatorial-entry.mjs
@greptile-apps

greptile-apps Bot commented Jun 9, 2026

Copy link
Copy Markdown

Greptile Summary

This PR migrates the combinatorial page entry point from .js to .mjs, refactoring the module into a testable factory (createCombinatorialPage) and adding three significant features: a live-updating estimate panel, a per-algorithm progress indicator with spinner animation, and a confirmation dialog before running large cartesian-product generations.

  • Architecture: DOM elements are injected rather than queried globally, and the confirm dialog is injected as requestConfirm, making the page unit-testable. The generation loop now yields to the browser between each algorithm so the UI stays responsive.
  • Safety: A try/finally block correctly re-enables the generate button even when an unexpected error is thrown mid-loop — a regression from the previous .js version.
  • CSS: Progress indicator colours are properly CSS-variabled for light and dark themes; the spinner respects prefers-reduced-motion.

Confidence Score: 5/5

Safe to merge — the core generation path is correct, the button re-enable regression is fixed with try/finally, and the new estimate/progress features are additive.

The refactored module correctly guards all the edge cases that were broken in the old .js file. The generate button is now always re-enabled via finally, formatNumber uses an explicit locale, and no new data-loss or breakage paths were introduced.

apps/web/src/combinatorial-entry.mjs — the two standalone calculation helpers create redundant model instances; minor cleanup suggested.

Important Files Changed

Filename Overview
apps/web/src/combinatorial-entry.mjs New page module replacing .js: adds live estimate panel, per-algorithm progress, yieldToBrowser for UI responsiveness, try/finally button re-enable, and cartesian confirmation dialog. Race window on button disable during confirm dialog remains (flagged in previous review).
apps/web/src/tests/jest/combinatorial-entry.test.js New Jest test file covering buildEstimateSummary, filterAlgorithmsForCartesianConfirmation, and page initialisation; sortResultsByRowCount and parseEnumParameters are exported but untested.
apps/web/styles.css Adds CSS variables for progress colours (light + dark), estimates panel styles, spinner animation with prefers-reduced-motion respect, and layout fixes for min-width/box-sizing.
apps/web/combinatorial.html Switches script src to .mjs, adds combinatorial-estimates div and combinatorial-progress paragraph with correct ARIA live-region attributes.
apps/web/src/combinatorial-entry.js File deleted; logic migrated to combinatorial-entry.mjs.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[User clicks Generate] --> B[parseEnumParameters]
    B --> C{Errors or < 2 params?}
    C -- yes --> D[setStatus error, return]
    C -- no --> E[renderControls]
    E --> F[getSelectedAlgorithms]
    F --> G{0 algorithms?}
    G -- yes --> H[setStatus error, return]
    G -- no --> I[filterAlgorithmsForCartesianConfirmation]
    I --> J{Cartesian + row count > threshold?}
    J -- no --> K[syncSelectedAlgorithms]
    J -- yes --> L[Show confirm dialog]
    L -- cancel --> M[Remove cartesian from list]
    L -- ok --> K
    M --> N{0 algorithms remain?}
    N -- yes --> O[setStatus warning, return]
    N -- no --> K
    K --> P[generateButton.disabled = true]
    P --> Q[Loop over algorithms]
    Q --> R[setProgress running]
    R --> S[yieldToBrowser]
    S --> T[runAlgorithm]
    T --> U{Throws?}
    U -- yes --> V[push error result]
    U -- no --> W[push success result]
    V --> X[renderSummary + renderDetails]
    W --> X
    X --> Y[yieldToBrowser]
    Y --> Q
    Q -- done --> Z[setStatus completed]
    Z --> AA[finally: button.disabled=false, setProgress empty]
Loading

Reviews (5): Last reviewed commit: "Scope combinatorial entry ESM fix" | Re-trigger Greptile

Comment thread apps/web/src/tests/jest/combinatorial-entry.test.js Outdated
Comment thread apps/web/src/combinatorial-entry.js Outdated
Comment thread apps/web/src/combinatorial-entry.mjs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
apps/web/styles.css (1)

1260-1271: ⚡ Quick win

Respect reduced-motion preferences for spinner animation

The running spinner animates indefinitely. Add a reduced-motion fallback to avoid unnecessary motion for users who opt out.

Suggested refactor
 `@keyframes` combinatorial-spin {
   to {
     transform: rotate(360deg);
   }
 }
+
+@media (prefers-reduced-motion: reduce) {
+  .combinatorial-progress[data-state='running']::before {
+    animation: none;
+  }
+}

Also applies to: 1338-1342

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/styles.css` around lines 1260 - 1271, The spinner animation defined
on the .combinatorial-progress[data-state='running']::before selector currently
animates indefinitely; add a reduced-motion fallback by using the
prefers-reduced-motion media query to disable the combinatorial-spin animation
(and reset any transforms) when users opt out — e.g., add `@media`
(prefers-reduced-motion: reduce) {
.combinatorial-progress[data-state='running']::before { animation: none; /*
reset transforms if needed */ } } and apply the same change for the other
spinner block that uses the combinatorial-spin keyframes to ensure both
locations respect reduced-motion preferences.
apps/web/src/tests/jest/combinatorial-entry.test.js (1)

64-69: ⚡ Quick win

Make the confirmation assertion less copy-fragile.

This test currently hard-codes the full dialog message text, which will fail on minor wording edits while behavior is still correct. Assert stable contract fields plus the row-count content instead.

Suggested diff
-    expect(requestConfirm).toHaveBeenCalledWith({
-      title: 'Cartesian product generation',
-      message: 'You included cartesian product generation. Are you sure? this will generate 100,000 data rows.',
-      okLabel: 'Run cartesian product',
-      cancelLabel: 'Skip cartesian product',
-    });
+    expect(requestConfirm).toHaveBeenCalledWith(
+      expect.objectContaining({
+        title: 'Cartesian product generation',
+        okLabel: 'Run cartesian product',
+        cancelLabel: 'Skip cartesian product',
+        message: expect.stringContaining('100,000'),
+      })
+    );
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/tests/jest/combinatorial-entry.test.js` around lines 64 - 69,
The assertion for requestConfirm is too brittle; update the test that calls
requestConfirm to assert the stable fields (title equals 'Cartesian product
generation', okLabel and cancelLabel text) and that the message contains the
dynamic row-count number (e.g., /100,000/ or computed rows variable) rather than
exact full message text. Locate the expectation using requestConfirm in
combinatorial-entry.test.js and replace the toHaveBeenCalledWith full-string
check with checks for the specific properties and a partial-match (string
contains / regex) on the message field.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/web/styles.css`:
- Around line 1253-1271: The .combinatorial-progress text color and spinner
(rules .combinatorial-progress and
.combinatorial-progress[data-state='running']::before) use `#1f5f80` which is
low-contrast on dark backgrounds; update the CSS to use theme-aware colors
(e.g., CSS variables or a prefers-color-scheme: dark override) so both the text
color and the spinner border-top-color change in dark mode to a lighter/contrast
color; modify the rules for .combinatorial-progress and
.combinatorial-progress[data-state='running']::before to reference the theme
variables (or add a dark media query) rather than the hard-coded `#1f5f80` so the
progress indicator remains readable in dark theme.

---

Nitpick comments:
In `@apps/web/src/tests/jest/combinatorial-entry.test.js`:
- Around line 64-69: The assertion for requestConfirm is too brittle; update the
test that calls requestConfirm to assert the stable fields (title equals
'Cartesian product generation', okLabel and cancelLabel text) and that the
message contains the dynamic row-count number (e.g., /100,000/ or computed rows
variable) rather than exact full message text. Locate the expectation using
requestConfirm in combinatorial-entry.test.js and replace the
toHaveBeenCalledWith full-string check with checks for the specific properties
and a partial-match (string contains / regex) on the message field.

In `@apps/web/styles.css`:
- Around line 1260-1271: The spinner animation defined on the
.combinatorial-progress[data-state='running']::before selector currently
animates indefinitely; add a reduced-motion fallback by using the
prefers-reduced-motion media query to disable the combinatorial-spin animation
(and reset any transforms) when users opt out — e.g., add `@media`
(prefers-reduced-motion: reduce) {
.combinatorial-progress[data-state='running']::before { animation: none; /*
reset transforms if needed */ } } and apply the same change for the other
spinner block that uses the combinatorial-spin keyframes to ensure both
locations respect reduced-motion preferences.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 48ae0eae-0dcd-4972-be76-a2cd396cedbd

📥 Commits

Reviewing files that changed from the base of the PR and between 37cc1d5 and a4bee9c.

📒 Files selected for processing (4)
  • apps/web/combinatorial.html
  • apps/web/src/combinatorial-entry.js
  • apps/web/src/tests/jest/combinatorial-entry.test.js
  • apps/web/styles.css

Comment thread apps/web/styles.css
Comment on lines +481 to +494
selectedAlgorithms = await filterAlgorithmsForCartesianConfirmation({
algorithms: selectedAlgorithms,
parameters,
requestConfirm,
});
syncSelectedAlgorithms(selectedAlgorithms);

if (selectedAlgorithms.length === 0) {
setStatus('Cartesian product run cancelled. No strategies remain selected.', 'warning');
setProgress('');
return;
}

generateButton.disabled = true;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Generate button clickable during Cartesian confirm dialog

generateButton.disabled = true is only set on line 494, after filterAlgorithmsForCartesianConfirmation has been awaited. When the confirm dialog is shown (cartesian product selected + row count > threshold), there is a window during which the button remains enabled. Clicking it a second time starts a second concurrent generateCombinatorial call, both of which will write to the same summaryRoot and detailsRoot DOM nodes and each will independently set the button back to enabled in their finally blocks, leaving execution state inconsistent.

Moving generateButton.disabled = true to before the filterAlgorithmsForCartesianConfirmation await (and re-enabling it in an early-return path if needed) prevents the race.

@eviltester eviltester merged commit eaa129a into master Jun 9, 2026
18 checks passed
@eviltester eviltester deleted the 167-combinatorial-test-bed-fixes branch June 9, 2026 16:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

combinatorial test bed fixes

2 participants